package net.jxtz.jxtzos.controller.achievements;


import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.jxtz.jxtzos.entity.achievements.Achievement;
import net.jxtz.jxtzos.entity.achievements.UserAchievement;
import net.jxtz.jxtzos.entity.achievements.dto.InitUserAchieve;
import net.jxtz.jxtzos.entity.web.R;
import net.jxtz.jxtzos.service.achievement.AchievementService;
import net.jxtz.jxtzos.service.achievement.UserAchievementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author a123
 */
@CrossOrigin
@RequestMapping("/user_achieve")
@RestController
@Slf4j
public class UserAchievementController {

    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public R add(@RequestBody UserAchievement userAchievement){
        Long achieveId = userAchievement.getAchieveId();
        Achievement byId = achievementService.getById(achieveId);
        Integer achieveNumber = userAchievement.getAchieveNumber();
        Double optionValue = byId.getOptionValue();
        Double aDouble = Double.valueOf(achieveNumber);
        Double price = optionValue * aDouble;
        Double maxOptionValue = byId.getMaxOptionValue();
        if (maxOptionValue != null && maxOptionValue != 0){
            if (price >= maxOptionValue){
                userAchievement.setAchievePrice(maxOptionValue);
            }else {
                userAchievement.setAchievePrice(price);
            }
        }else {
            // 如果最大产值为0或者为null则说明没有最大产值限制
            userAchievement.setAchievePrice(price);
        }

        boolean save = userAchievementService.save(userAchievement);
        return save? R.ok().data("userAchievement", userAchievement): R.error();
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    public R delete(@PathVariable Long id){
        boolean save = userAchievementService.removeById(id);
        return save? R.ok():R.error();
    }

    @RequestMapping(value = "/getList", method = RequestMethod.GET)
    public R getList(){
        List<UserAchievement> list = userAchievementService.list();
        return R.ok().data("list", list);
    }

    @RequestMapping(value = "/page", method = RequestMethod.GET)
    public R getPage(@RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize, @RequestParam(value = "time", required = false) Integer time, @RequestParam(value = "userId" , required = false) Long userId){
        HashMap<String, Object> map = new HashMap<>();
        if (time != null && time != 0){
            map.put("achieve_time", time);
        }
        if (userId != null && userId != 0){
            map.put("user_id", userId);
        }

        Page<UserAchievement> page = userAchievementService.page(new Page<>(pageNum, pageSize), new QueryWrapper<UserAchievement>().orderByDesc("achieve_time").allEq(map));
        List<UserAchievement> records = page.getRecords();
        long total = page.getTotal();
        return R.ok().data("list", records).data("total", total);
    }

    @Transactional
    @RequestMapping(value = "/getListByUserId", method = RequestMethod.GET)
    public R getList(@RequestParam("userId") Long id, @RequestParam("tabId") Long tabId, @RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize){

        // 所有子项
        List<Achievement> fatherId = achievementService.list(new QueryWrapper<Achievement>().eq("father_id", tabId));
        List<UserAchievement> list = new ArrayList<>();
        for (Achievement achievement : fatherId) {
            Map<String, Long> map = new HashMap<>();
            map.put("user_id", id);
            map.put("achieve_id", achievement.getId());
            List<UserAchievement> list1 = userAchievementService.list(new QueryWrapper<UserAchievement>().allEq(map).orderByDesc("achieve_time"));
            list.addAll(list1);
        }

        int size = list.size();
        List<UserAchievement> collect = list.stream()
                // 分页
                .skip((long) (pageNum - 1) * pageSize).limit(pageSize)
                // 排序
                .sorted(Comparator.comparing(UserAchievement::getAchieveTime).reversed())
                .collect(Collectors.toList());

        return R.ok().data("list", collect).data("total", size);
    }

    @RequestMapping(value = "/excel", method = RequestMethod.POST)
    public void excel(HttpServletResponse response){
        List<InitUserAchieve> list = userAchievementService.getInitUserAchieveList();
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("月度绩效", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), InitUserAchieve.class).autoCloseStream(Boolean.TRUE).sheet("月度绩效")
                    .doWrite(list);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            try {
                response.getWriter().println(JSON.toJSONString(R.ok().message("下载文件失败")));
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }


    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public R update(@RequestBody UserAchievement userAchievement){
        boolean save = userAchievementService.updateById(userAchievement);
        return save? R.ok():R.error();
    }

    private final UserAchievementService userAchievementService;

    private final AchievementService achievementService;

    @Autowired
    public UserAchievementController(UserAchievementService userAchievementService, AchievementService achievementService){
        this.userAchievementService = userAchievementService;
        this.achievementService = achievementService;
    }

}
